package com.yzc.android.network.base;

import android.text.TextUtils;

import java.util.HashMap;
import java.util.Map;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.orhanobut.logger.Logger;
import com.yzc.android.KDApp;
import com.yzc.android.network.mock.IFakeResponse;
import com.yzc.android.utils.LogUtils;
import org.json.JSONArray;
import org.json.JSONObject;

/**
 * Created by yzc on 16/2/1.
 */
public abstract class KDBaseRequest<T> extends Request<T> {
    public static String loggerTag = "Volley";

    protected final Gson gson = new GsonBuilder().setPrettyPrinting().create();

    /** Charset for request. */
    protected static final String PROTOCOL_CHARSET = "utf-8";

    /** Content type for request. */
    protected static final String PROTOCOL_CONTENT_TYPE =
            String.format("application/json; charset=%s", PROTOCOL_CHARSET);

    private final Response.Listener<T> mListener;
    protected final String mRequestBody;
    private final Map<String, String> headers;
    private final Map<String, String> params;

    private IFakeResponse mFakeResponse;

    public KDBaseRequest(int method,
                         Map<String, String> headers,
                         Map<String, String> params,
                         String requestBody,
                         Response.Listener<T> listener,
                         Response.ErrorListener errorListener) {
        super(method, generateFinalUrl(params!=null ? params.get("method") : null), errorListener);
        this.mListener = listener;
        this.mRequestBody = requestBody;
        this.headers = addCommonHeaders(headers);
        this.params = addCommonParams(params);
    }

    public KDBaseRequest(int type,
                         Map<String, String> headers,
                         Map<String, String> params,
                         Response.Listener<T> listener,
                         Response.ErrorListener errorListener) {
        super(type, generateFinalUrl(params!=null ? params.get("method") : null), errorListener);
        this.headers = addCommonHeaders(headers);
        this.params = addCommonParams(params);
        this.mListener = listener;
        this.mRequestBody = null;
    }

    public KDBaseRequest(int type,
                         String hostUrl,
                         Map<String, String> headers,
                         Map<String, String> params,
                         Response.Listener<T> listener,
                         Response.ErrorListener errorListener) {
        super(type, hostUrl, errorListener);
        this.headers = addCommonHeaders(headers);
        this.params = addCommonParams(params);
        this.mListener = listener;
        this.mRequestBody = null;
    }

    public IFakeResponse getFakeResponse() {
        return mFakeResponse;
    }

    public void setFakeResponse(final IFakeResponse fakeResponse) {
        mFakeResponse = fakeResponse;
    }

    @Override
    protected void deliverResponse(T response) {
        if (response instanceof KDBaseResponse)
        {
            KDBaseResponse baseResponse = (KDBaseResponse) response;
            if (baseResponse.code == BaseErrorCode.SERVER_BACK_CODE_SUCCESS)
            {
                if(null != mListener){
                    mListener.onResponse(response);
                }
            }
            else if (baseResponse.code == BaseErrorCode.SERVER_BACK_CODE_BAD_TOKEN)
            {
                LogUtils.e(loggerTag, "USER, back token");
                showBadTokenAlert();
            }
            else
            {
                KDVolleyError error = new KDVolleyError(baseResponse.code, baseResponse.message);
                deliverError(error);
            }
        }
        else if (response instanceof JSONObject)
        {
            JSONObject jsonObject = (JSONObject) response;
            int state = jsonObject.optInt("code");
            if (state == BaseErrorCode.SERVER_BACK_CODE_SUCCESS)
            {
                if(null != mListener){
                    mListener.onResponse(response);
                }
            }
            else if (state == BaseErrorCode.SERVER_BACK_CODE_BAD_TOKEN)
            {
                Logger.t(loggerTag).d("USER, back token");
                showBadTokenAlert();
            }
            else
            {
                KDVolleyError error = new KDVolleyError(jsonObject.optInt("code"), jsonObject.optString("message"));
                deliverError(error);
            }
        }
        else if (response instanceof JSONArray)
        {
            //JSONArray jsonArray = (JSONArray) response;
            if (mListener != null)
            {
                mListener.onResponse(response);
            }
        }
        else
        {
            if (mListener != null)
            {
                mListener.onResponse(response);
            }
        }
    }

    @Override
    protected abstract Response<T> parseNetworkResponse(NetworkResponse response);

    @Override
    protected VolleyError parseNetworkError(VolleyError volleyError) {
        VolleyError error = super.parseNetworkError(volleyError);
        try {
            String paramJson = gson.toJson(getParams());
            LogUtils.t(loggerTag).d("network error%nmethod=%s%nparams=%s%nerror=%s", getUrl(), paramJson, error.toString());
        }
        catch (Exception e)
        {
            LogUtils.t(loggerTag).d("network error%nmethod=%s%nerror=%s", getUrl(), error.toString());
        }
        return error;
    }


    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        return headers != null ? headers : super.getHeaders();
    }

    @Override
    protected Map<String, String> getParams() throws AuthFailureError {
        return params != null ? params : super.getParams();
    }

    public String getRequestMethod()
    {
        return params!=null ? params.get("method") : null;
    }

    private static Map<String, String> addCommonParams(Map<String, String> params)
    {
        Map<String, String> result = new HashMap<>();
        if (params != null)
        {
            result.putAll(params);
        }
        //result.put("appkey", String.valueOf(AppInfo.APP_KEY));
        //result.put("from", AppInfo.getChannel());
        //result.put("udid", TextUtils.isEmpty(AppInfo.UDID) ? PhoneFunc.getImei() : AppInfo.UDID);
        //result.put("macaddress", PhoneFunc.getMacAddress());
        //result.put("td_appcpa_channel", AppInfo.CHANELID);
        //result.put("ver", "3");
        //result.put("timestamp", TimeUtil.getcurrentTimes());
        //result.put("app_ver", UpgradeManager.getAppVersion());
        //result.put("os", "android " + android.os.Build.VERSION.RELEASE);
        //result.put("model", android.os.Build.MODEL);
        //if(!result.containsKey("token") && !TextUtils.isEmpty(UserStatusManager.getToken())) {
        //    result.put("token", UserStatusManager.getToken());
        //}
        ////用户手机号，此处为了保护用户隐私，只传手机号的MD5值，查log时，拿到用户手机号，先转换成MD5值，再用这个当作唯一标识查询
        //String phone = null;
        //if(UserStatusManager.getUserInfo()!=null) {
        //    phone = UserStatusManager.getUserInfo().phone;
        //}
        //if (!result.containsKey(Constants.KEY_LOGIN_PHONE)
        //        && !TextUtils.isEmpty(phone)) {
        //    result.put(Constants.KEY_LOGIN_PHONE, MD5.md5(phone.trim()));
        //}
        ////用户位置
        //Address address = Const.LOCATION_CONTROLLER.getLocationAddress();
        //if(null != address) {
        //    //用户位置(经纬度)
        //    if( !result.containsKey(Constants.KEY_LAT)
        //            && !result.containsKey(Constants.KEY_LATITUDE)
        //            && !result.containsKey(Constants.KEY_CUSTOMER_LAT)) {
        //        result.put(Constants.KEY_LAT, address.lat + "");
        //        result.put(Constants.KEY_LNG, address.lng + "");
        //    }
        //    //当前所在城市
        //    String cityId = Const.LOCATION_CONTROLLER.getLocationAddress().cityId;
        //    if ( !result.containsKey(Constants.KEY_CURRENT_CITY_ID)
        //            && !TextUtils.isEmpty(cityId)) {
        //        result.put(Constants.KEY_CURRENT_CITY_ID, cityId);
        //    }
        //}
        //result.put("from_type", "app");
        //result.put("sig", Utils.toSortMD5(result));
        return result;
    }

    private static Map<String, String> addCommonHeaders(Map<String, String> headers)
    {
        Map<String, String> result = new HashMap<>();
        if (headers != null)
        {
            result.putAll(headers);
        }
        //result.put("device_id", AppInfo.DEVICE_ID);
        return result;
    }

    private static String generateFinalUrl(String method)
    {
        if (TextUtils.isEmpty(method)) return null;
        String result = KDApp.getInstance().getAppConfigManager().getApiHostUrl();
        result = result + "?method=" + method;
        return result;
    }

    /**
     * 显示Token过期对话框
     *
     */
    private static void showBadTokenAlert() {
        //if (!TextUtils.isEmpty(UserStatusManager.getToken())) {//避免多次弹框
        //    Activity activity = EDJApp.getInstance().getLastActivity();
        //    if (activity != null) {
        //        DialogUtil.showEDJInformationDialog(activity, "", activity.getResources().getString(R.string.badtoken_title), activity.getResources().getString(R.string.dialog_ok), new EDJCustomDialog.DialogBtnClickListener() {
        //            @Override
        //            public void onClick(Dialog dialog, EDJCustomDialog.eBtnType type) {
        //                Intent intent = new Intent();
        //                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        //                intent.setClass(EDJApp.getInstance(), LoginActivity.class);
        //                EDJApp.getInstance().startActivity(intent);
        //                dialog.dismiss();
        //            }
        //        });
        //    }
        //}
    }
}
